//==============================================================================
//
//  File        : sensor_AR0330.c
//  Description : Firmware Sensor Control File
//  Author      : JengWei Liaw
//  Revision    : 1.0
//
//=============================================================================

#include "includes_fw.h"
#if defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW)||(SENSOR_EN)
#include "config_fw.h"

#if BIND_SENSOR_AR0330

#include "lib_retina.h"
#include "reg_retina.h"

#include "mmp_reg_vif.h"
#include "mmp_reg_scaler.h"
#include "mmp_reg_gpio.h"
#include "mmp_reg_rawproc.h"

#include "mmpf_sensor.h"
#include "mmpf_hif.h"
#include "mmpf_i2cm.h"
#include "mmpf_vif.h"
#include "isp_if.h"
#include "mmpf_usbpccam.h"

#include "mmp_reg_i2cm.h"
#include "mmps_3gprecd.h"
#include "sensor_AR0330.h"
#include "hdm_ctl.h"
#include "mmpf_dram.h"
#include "motor_ctl.h"
#include "flash_ctl.h"
#include "mmpf_pll.h"

static MMPF_I2CM_ATTRIBUTE m_snr_I2cmAttribute = {
            SENSOR_I2CM_ID, SENSOR_I2C_ADDR_AR0330, 16, 16, 0, MMP_FALSE, MMP_FALSE, MMP_FALSE,
            MMP_FALSE, 0, 0, 0, MMPF_I2CM_SPEED_HW_250K, NULL, NULL};

#ifndef SENSOR_ID_AR0330
#define SENSOR_ID_AR0330 0
#endif

MMP_USHORT gsEnableTestPattern = 0;

static	MMP_UBYTE   vif_id = 0;

#define G2_CLK                      (120)

extern MMP_USHORT  gsSensorPreviewWidth[], gsSensorPreviewHeight[];
extern MMP_USHORT  gsCurPreviewMode, gsCurPhaseCount;
extern MMP_USHORT  m_usVideoQuality;
extern MMP_USHORT	m_gsISPCoreID;

extern MMPS_3GPRECD_VIDEO_FORMAT m_VideoFmt;
extern MMP_BOOL    gbAutoFocus;

extern MMP_USHORT m_usResolType;
extern MMP_ULONG   glPccamResolution;
extern H264_FORMAT_TYPE gbCurH264Type;

#if (IQ_TABLE_LOAD_FROM_FLASH == 0)
ISP_UINT8 Sensor_IQ_CompressedText[] = {
//#include "isp_8451_iq_data_v2_AR0330.xls.ciq.txt"
#include "isp_8451_iq_data_v2_AR0330.xls.iq.txt"
};
#endif

#define  SENSOR_ROTATE_180    0   

#define  PIXEL_RATE_60M      (1)
#define  PIXEL_RATE_42M      (2)

#define VOLTAGE33V 0
#define VOLTAGE28V 1
#define VOLTAGE18V 2

#define SENSOR_VOLTAGE      VOLTAGE18V

#define  SENSOR_PIXEL_RATE          (PIXEL_RATE_42M)

#define BASE_SHUTTER_50HZ		408
#define BASE_SHUTTER_60HZ		340

void SNR_AR0330_SetSensorResolution_Customer(ISP_SENSOR_RESOL res);
void SNR_AR0330_InitSensor_Customer(void);
#if SUPPORT_AUTO_FOCUS
void MOTOR_AR0330_VCM_InitMotor_Customer(void);
void MOTOR_AR0330_VCM_SetAFPosition_Customer(MMP_USHORT af_pos);
#endif

static VENUS_SYSTEM_MODE gSystemMode;

MMP_LONG g_SNR_LineCntPerSec = 1;
//------------------------------------------------------------------------------
//  Function    : AR0330_Sensor_PreviewMode
//  Description :
//------------------------------------------------------------------------------
extern MMP_BYTE gbSignalType;
extern MMPF_SENSOR_FUNCTION *gsSensorFunction ;

static void AR0330_Sensor_PreviewMode(MMP_USHORT usPreviewmode)
{
    gsCurPreviewMode = usPreviewmode;

    switch (usPreviewmode) {
    case 0:
        RTNA_DBG_Str(0, "Sensor 5M (2560x1920) preview mode\r\n");
        gsSensorFunction->MMPF_Sensor_Set3AStatus(MMP_FALSE);

        gSystemMode = VENUS_SYSTEM_MODE_PREVIEW;//ISP_IF_SNR_SetBeforePreview();
        ISP_IF_IQ_SetSysMode(1); //Steven NOTE:please reference excel define: 0=capture, 1=preview, 2=video....
        SNR_AR0330_SetSensorResolution_Customer(ISP_SENSOR_RESOL_2560x1920);

        //set color transform 16 ~ 235
        MMPF_Scaler_SetOutputColor(MMPF_SCALER_PATH_0, MMP_TRUE, MMPF_SCALER_COLRMTX_BT601); //YUV or H264 run BT601 , MPEG run FULLRANGE

        ISP_IF_AE_SetFPS(0);
        gsSensorFunction->MMPF_Sensor_Set3AStatus(MMP_TRUE);
        break;
    case 1:
        RTNA_DBG_Str(0, "Sensor 3M (2304x1296) preview mode\r\n");
        gsSensorFunction->MMPF_Sensor_Set3AStatus(MMP_FALSE);

        gSystemMode = VENUS_SYSTEM_MODE_PREVIEW;//ISP_IF_SNR_SetBeforePreview();
        ISP_IF_IQ_SetSysMode(1); //Steven NOTE:please reference excel define: 0=capture, 1=preview, 2=video....
        SNR_AR0330_SetSensorResolution_Customer(ISP_SENSOR_RESOL_2304x1296);

        //set color transform 16 ~ 235
        MMPF_Scaler_SetOutputColor(MMPF_SCALER_PATH_0, MMP_TRUE, MMPF_SCALER_COLRMTX_BT601); //YUV or H264 run BT601 , MPEG run FULLRANGE

        ISP_IF_AE_SetFPS(0);
        gsSensorFunction->MMPF_Sensor_Set3AStatus(MMP_TRUE);
        break;
    case 2:
        RTNA_DBG_Str(0, "Sensor 1.3M (1280x720) preview mode\r\n");
        gsSensorFunction->MMPF_Sensor_Set3AStatus(MMP_FALSE);

        gSystemMode = VENUS_SYSTEM_MODE_PREVIEW;//ISP_IF_SNR_SetBeforePreview();
        ISP_IF_IQ_SetSysMode(1); //Steven NOTE:please reference excel define: 0=capture, 1=preview, 2=video....
        SNR_AR0330_SetSensorResolution_Customer(ISP_SENSOR_RESOL_1280x720);

        //set color transform 16 ~ 235
        MMPF_Scaler_SetOutputColor(MMPF_SCALER_PATH_0, MMP_TRUE, MMPF_SCALER_COLRMTX_BT601); //YUV or H264 run BT601 , MPEG run FULLRANGE

        ISP_IF_AE_SetFPS(0);
        gsSensorFunction->MMPF_Sensor_Set3AStatus(MMP_TRUE);
        break;
    }
}
extern void GPIO_OutputControl(MMP_UBYTE num, MMP_UBYTE status);
extern volatile MMP_UBYTE   gbDramID;
//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_Initialize
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_Initialize_AR0330(void)
{
    AITPS_VIF   pVIF = AITC_BASE_VIF;

    RES_TYPE_CFG *cur_res;
    
    RTNA_DBG_Str(0, "MMPF_Sensor_Initialize_AR0330...Begin\r\n");

    //Init globol variable used by DSC
    gsSensorPreviewWidth[0] = 2304;
    gsSensorPreviewHeight[0] = 1296;
    // use 1.3M for preview, check sensor preview setting
    gsSensorPreviewWidth[1] = 2304;
    gsSensorPreviewHeight[1] = 1296;

    if((gbDramID == MMPF_DRAMID_WINBOND_SDR16) || (gbDramID == MMPF_DRAMID_WINBOND_SDR16_1_8V)){
        GPIO_OutputControl(GPIO_SENSOR_PSEN, MMP_TRUE);
        MMPF_OS_Sleep_MS(5);
        GPIO_OutputControl(GPIO_SENSOR_PSEN, MMP_FALSE);
    }
    else{
        MMPF_VIF_SetPIODir(VIF_SIF_SEN, MMP_TRUE);
        MMPF_VIF_SetPIOOutput(VIF_SIF_SEN, MMP_TRUE);  //Pin output high
        MMPF_OS_Sleep_MS(5);
    }

    GPIO_OutputControl(SEN_PWR_EN, MMP_TRUE);
    MMPF_OS_Sleep_MS(5);
    MMPF_VIF_SetPIOOutput(VIF_SIF_SEN, MMP_FALSE);  //Pin output low

    pVIF->VIF_SENSR_CLK_CTL[vif_id] = VIF_SENSR_CLK_EN;
    MMPF_OS_Sleep_MS(5);

    GPIO_OutputControl(SEN_RST, MMP_FALSE);
    MMPF_OS_Sleep_MS(5);
    GPIO_OutputControl(SEN_RST, MMP_TRUE);

    /*Reset Sensor 500mS*/
    MMPF_VIF_SetPIODir(VIF_SIF_RST, MMP_TRUE);
    MMPF_VIF_SetPIOOutput(VIF_SIF_RST, MMP_FALSE);
    MMPF_OS_Sleep_MS(10);
    MMPF_VIF_SetPIOOutput(VIF_SIF_RST, MMP_TRUE);
    MMPF_OS_Sleep_MS(20);
    #if 1// debug for checking I2C access
    {
        MMP_USHORT chipid, tmpdata;
        gsSensorFunction->MMPF_Sensor_GetReg(0x20, &tmpdata);
        chipid = tmpdata<<8;
        gsSensorFunction->MMPF_Sensor_GetReg(0x21, &tmpdata);
        chipid |= (tmpdata & 0xFF);
        if(chipid!=0xFFFF) {
            RTNA_DBG_Str(0, "Chip ID:");
            RTNA_DBG_Short(0, chipid);
            RTNA_DBG_Str(0, "\r\n");
        }
        else {
            RTNA_DBG_Str(0, "Chip ID Read error! Check sensor and I2C\r\n");
        }
    }
    #endif

    SNR_AR0330_InitSensor_Customer();

    cur_res = GetResCfg(glPccamResolution);
    if(cur_res->res_w > gsSensorPreviewWidth[1] || cur_res->res_h > gsSensorPreviewHeight[1]) {
        gsSensorFunction->MMPF_Sensor_SetPreviewMode(0);
    }
    else {
        gsSensorFunction->MMPF_Sensor_SetPreviewMode(1);
    }

#if SUPPORT_AUTO_FOCUS
    MOTOR_AR0330_VCM_InitMotor_Customer();
#endif

#if SUPPORT_FLASH_LIGHT
    VR_Flash_Init();
#endif

    RTNA_DBG_Str(0, "MMPF_Sensor_Initialize_AR0330...End\r\n");
    return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_PowerDown_AR0330
//  Description :
//------------------------------------------------------------------------------

static MMP_ERR  MMPF_Sensor_PowerDown_AR0330(void)
{
    AITPS_VIF  pVIF = AITC_BASE_VIF;
    #if (CUSTOMER == PNS) && SUPPORT_UAC
    AITPS_GPIO	pGPIO = AITC_BASE_GPIO;
    AITPS_GBL   pGBL = AITC_BASE_GBL;
    #endif

    MMPF_VIF_EnableInputInterface(MMP_FALSE);

    MMPF_VIF_SetPIOOutput(VIF_SIF_RST, MMP_FALSE);//Pin output low
    MMPF_OS_Sleep_MS(10);

    if((gbDramID == MMPF_DRAMID_WINBOND_SDR16) || (gbDramID == MMPF_DRAMID_WINBOND_SDR16_1_8V)){
        GPIO_OutputControl(GPIO_SENSOR_PSEN, MMP_TRUE);
    }
    else{
        MMPF_VIF_SetPIODir(VIF_SIF_SEN, MMP_TRUE);
        MMPF_VIF_SetPIOOutput(VIF_SIF_SEN, MMP_TRUE);  //Pin output high
    }
    MMPF_OS_Sleep_MS(5);
    GPIO_OutputControl(SEN_PWR_EN, MMP_FALSE);

    pVIF->VIF_SENSR_CLK_CTL[vif_id] &= (~ VIF_SENSR_CLK_EN) ;   //output sensor main clock

    #if (CUSTOMER == LGT) || (CUSTOMER == CCN) || (CUSTOMER == SNO) || (CUSTOMER == CPL) 
    GPIO_OutputControl(CAM_EN, FALSE);
    MMPF_OS_Sleep_MS(10);
    #endif

    MMPF_OS_Sleep_MS(20);

    RTNA_DBG_Str3( "MMPF_Sensor_PowerDown_AR0330() \r\n");
    return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_SetFrameRate_AR0330
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_SetFrameRate_AR0330(MMP_UBYTE ubFrameRate)
{
    return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_SetPreviewMode
//  Description :
//------------------------------------------------------------------------------

static MMP_ERR MMPF_Sensor_SetPreviewMode_AR0330(MMP_USHORT usPreviewmode)
{
    AR0330_Sensor_PreviewMode(usPreviewmode);

    return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_SetPreviewMode
//  Description :
//------------------------------------------------------------------------------

static MMP_ERR MMPF_Sensor_ChangePreviewMode_AR0330(
                        MMP_USHORT usCurPreviewmode, MMP_USHORT usCurPhasecount,
                        MMP_USHORT usNewPreviewmode, MMP_USHORT usNewPhasecount)
{
    AR0330_Sensor_PreviewMode(usNewPreviewmode);

    return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_ChangeMode
//  Description :
//------------------------------------------------------------------------------

/*static*/ MMP_ERR MMPF_Sensor_ChangeMode_AR0330(MMP_USHORT usPreviewmode, MMP_USHORT usCapturemode)
{
    switch (usPreviewmode) {
    case 0:
        switch (usCapturemode) {
        case 0:
            break;
        case 1:
            break;
        }
        break;
    case 1:
        switch (usCapturemode) {
        case 0:// SXGA preview, 5M capture
            MMPF_Sensor_SetPreviewMode_AR0330(0);
            // wait 3 frame ...
            // MMPF_Sensor_WaitFrame(5);
            break;
        case 1:
            MMPF_Sensor_SetPreviewMode_AR0330(1);
            // wait 3 frame ...
            //MMPF_Sensor_WaitFrame(3);
            break;
        }
        break;
    }

    return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_InitializeVIF
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_InitializeVIF_AR0330(void)
{
    AITPS_MIPI  pMIPI = AITC_BASE_MIPI;
    AITPS_VIF  pVIF = AITC_BASE_VIF;
    ISP_HDM_VIF_IF vif_if;
    MMP_ULONG   ulSENSORCLK;

    // register sensor (functions and variables)
    //ISP_IF_SNR_Register();
    RTNA_DBG_Str(0, "ISP_IF_SNR_Register...E\r\n");

    #if SUPPORT_AUTO_FOCUS
    #if (CUSTOMER == NMG)  
    GPIO_OutputControl(AF_EN, TRUE);
    #endif
    MMPF_OS_Sleep_MS(20);
    #endif

#if SUPPORT_AUTO_FOCUS
    // register motor
//	ISP_IF_MOTOR_Register();
#endif

    #if (SENSOR_IF == SENSOR_IF_PARALLEL)
    MMPF_VIF_RegisterInputInterface(MMPF_VIF_PARALLEL);
    pVIF->VIF_SENSR_CTL[vif_id] = VIF_SENSR_LATCH_PST | VIF_LINE_ID_POLAR | VIF_PIXL_ID_POLAR | VIF_VSYNC_POLAR_NEG;
    #else
    #if 0
    pMIPI->MIPI_DATA1_SOT = 0x10; // From KW
    pMIPI->MIPI_DATA2_SOT = 0x10; // From KW
    pMIPI->MIPI_DATA3_SOT = 0x10; // From KW
    pMIPI->MIPI_DATA4_SOT = 0x10; // From KW
    #endif

    pMIPI->MIPI_DATA0_DLY[vif_id] = 0x1000;  // set SOT counter to 0x10
    pMIPI->MIPI_DATA1_DLY[vif_id] = 0x1000;  // set SOT counter to 0x10

    MMPF_VIF_RegisterInputInterface(MMPF_VIF_MIPI);
    #endif

    // initialize VIF OPRs
#if (SENSOR_IF == SENSOR_IF_PARALLEL)
    vif_if = ISP_HDM_VIF_IF_PARALLEL;		//ISP_HDM_IF_InitVIF(ISP_HDM_VIF_IF_PARALLEL, 22);
#elif (SENSOR_IF == SENSOR_IF_MIPI_1_LANE)	
    vif_if = ISP_HDM_VIF_IF_MIPI_SINGLE_0;	//ISP_HDM_IF_InitVIF(ISP_HDM_VIF_IF_MIPI_SINGLE_0, 22);
#elif (SENSOR_IF == SENSOR_IF_MIPI_2_LANE)		
    vif_if = ISP_HDM_VIF_IF_MIPI_DUAL_01;	//ISP_HDM_IF_InitVIF(ISP_HDM_VIF_IF_MIPI_DUAL_01, 22);
#elif (SENSOR_IF == SENSOR_IF_MIPI_4_LANE)		
    vif_if = ISP_HDM_VIF_IF_MIPI_QUAD;		//ISP_HDM_IF_InitVIF(ISP_HDM_VIF_IF_MIPI_QUAD, 22);
#endif	

    {
        pVIF->VIF_INT_HOST_EN[vif_id] = 0;
        pVIF->VIF_INT_CPU_SR[vif_id] = VIF_INT_ALL;
        pVIF->VIF_OUT_EN[vif_id] = 0;
        //pVIF->VIF_DEFT_EN = 0;
        pVIF->VIF_RAW_OUT_EN[vif_id] = 0;
        pVIF->VIF_FRME_SKIP_NO[vif_id] = 0;
        pVIF->VIF_FRME_SKIP_EN[vif_id] = 0;

        //RTNA_DBG_Str(0,"InitializeVIF\r\n");
        MMPF_PLL_GetGroupFreq(4, &ulSENSORCLK);

        switch(ulSENSORCLK) {
            case 96000:
                pVIF->VIF_SENSR_CLK_FREQ[vif_id] = VIF_SENSR_CLK_PLL_D4;
                RTNA_DBG_Str3("96MHz DIV 4\r\n");
                break;
            case 144000:
                pVIF->VIF_SENSR_CLK_FREQ[vif_id] = VIF_SENSR_CLK_PLL_D6; 
                RTNA_DBG_Str3("144MHz DIV 6\r\n");
                break;
            case 192000:
                pVIF->VIF_SENSR_CLK_FREQ[vif_id] = VIF_SENSR_CLK_PLL_D8;
                RTNA_DBG_Str3("192MHz DIV 8\r\n");
                break;
            case 216000:
                pVIF->VIF_SENSR_CLK_FREQ[vif_id] = VIF_SENSR_CLK_PLL_D9;
                RTNA_DBG_Str3("216MHz DIV 9\r\n");
                break;
            case 240000:
                pVIF->VIF_SENSR_CLK_FREQ[vif_id] = VIF_SENSR_CLK_PLL_D10;
                RTNA_DBG_Str3("240MHz DIV 10\r\n");
                break;
            case 120000:
                pVIF->VIF_SENSR_CLK_FREQ[vif_id] = VIF_SENSR_CLK_PLL_D5;
                RTNA_DBG_Str3("120MHz DIV 5\r\n");
                break;
            default:
                pVIF->VIF_SENSR_CLK_FREQ[vif_id] = VIF_SENSR_CLK_PLL_D12;
                break;
        }

        #if (SENSOR_IF==SENSOR_IF_PARALLEL)
        pVIF->VIF_SENSR_CTL[vif_id] = VIF_SENSR_LATCH_PST | VIF_LINE_ID_POLAR | VIF_PIXL_ID_POLAR | VIF_VSYNC_POLAR_NEG;		
        #elif (SENSOR_IF==SENSOR_IF_MIPI_2_LANE)
        pVIF->VIF_SENSR_CTL[vif_id] = VIF_SENSR_LATCH_PST | VIF_PIXL_ID_POLAR;
        #endif	

		pVIF->VIF_YUV_CTL[vif_id] = VIF_YUV_FORMAT_VUY;
        pVIF->VIF_SENSR_CLK_CTL[vif_id] = VIF_SENSR_CLK_EN;
        pVIF->VIF_OPR_UPD[vif_id] = VIF_OPR_UPD_EN | VIF_OPR_UPD_FRAME;

        if (vif_if==ISP_HDM_VIF_IF_PARALLEL) {
            RTNA_DBG_Str0("ISP_HDM_VIF_IF_PARALLEL\r\n");
        }
        else {
            pMIPI->MIPI_DATA0_CFG[vif_id] = ((pMIPI->MIPI_DATA0_CFG[vif_id] & ~MIPI_DAT_SRC_SEL_MASK) | MIPI_DAT_SRC_PHY_1) | MIPI_CSI2_EN;
            if (vif_if == ISP_HDM_VIF_IF_MIPI_DUAL_01) {
                pMIPI->MIPI_DATA1_CFG[vif_id] = ((pMIPI->MIPI_DATA1_CFG[vif_id] & ~MIPI_DAT_SRC_SEL_MASK) | MIPI_DAT_SRC_PHY_2) | MIPI_CSI2_EN;
            }
            #if (CHIP == P_V2)
            else if(vif_if==ISP_HDM_VIF_IF_MIPI_QUAD){
                pMIPI->MIPI_DATA2_CFG = MIPI_CSI2_EN | MIPI_SRC_SEL_2;
                pMIPI->MIPI_DATA3_CFG = MIPI_CSI2_EN | MIPI_SRC_SEL_3;
                pMIPI->MIPI_DATA4_CFG = MIPI_CSI2_EN | MIPI_SRC_SEL_4;
            }
            #endif
        }
    }
	return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_InitializeISP
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_InitializeISP_AR0330(void)
{
    // register sensor (functions and variables)
    RTNA_DBG_Str(0, "ISP_IF_LIB_Init...\r\n");
    // check if ISP Lib and IQ are mismatched.
    ISP_IF_LIB_Init();
    // check if ISP Lib and IQ are mismatched.
    if (ISP_IF_LIB_CompareIQVer() != MMP_ERR_NONE) {
        RTNA_DBG_Str(0, "Wrong ISP lib version!\r\n");
        return MMP_ERR_NONE;
    }

    //RTNA_DBG_Str(0, "ISP_IF_3A_Init...S\r\n");
    // initialize 3A
    ISP_IF_3A_Init();

    // set AF type (ISP_AF_TYPE_ONE_SHOT / ISP_AF_TYPE_CONTINUOUS)
    ISP_IF_AF_SetType(ISP_AF_TYPE_CONTINUOUS);
    //RTNA_DBG_Str(0, "ISP_IF_3A_Init...E\r\n");

    //ISP_IF_AE_SetLowLuxMode(0);//disable Low light Compensation

    return  MMP_ERR_NONE;
}

//============================================================================

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_SetAFPosition_AR0330
//  Description :
// ---------------------------------------
static MMP_ERR MMPF_Sensor_SetAFPosition_AR0330(MMP_UBYTE ubPos)
{
#if SUPPORT_AUTO_FOCUS
    ISP_IF_AF_SetPos(ubPos, 8);
    MOTOR_AR0330_VCM_SetAFPosition_Customer(ISP_IF_AF_GetPos(0));

    //RTNA_DBG_Str(3, "  ubPos = ");       
    //RTNA_DBG_Short(3, ubPos);
    //RTNA_DBG_Str(3, "\r\n");
#endif
    return  MMP_ERR_NONE;
}

#define MinFrameDivsor 5 // Gason@20120111, by OV suggestion, under 15 fps, dummy line will work every 5 frame.
static ISP_UINT32 frame_div = 5;
static ISP_UINT32 gISPFrameCnt = 0;
//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_Do3AOperation
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_DoAWBOperation_AR0330(void)
{
if(!gsEnableTestPattern)
{
    switch (gISPFrameCnt % frame_div) {
    case 3:
#if 1
        //	ISP_IF_R_DoAWB();
        ISP_IF_AWB_Execute();
        ISP_IF_CALI_Execute();
        ISP_IF_IQ_SetAWBGains(ISP_IF_AWB_GetGainR(), ISP_IF_AWB_GetGainG(), ISP_IF_AWB_GetGainB(), ISP_IF_AWB_GetGainBase());
#endif
        break;
    }
}
    return  MMP_ERR_NONE;
}


ISP_UINT32 s_gain, ISPgain; //For Color patch infor
//------------------------------------------------------------------------------
// for sensor table search
//------------------------------------------------------------------------------

const ISP_UINT32 get_ActualAnalogGain[16] = {
    0x00010000,
    0x000107AE,
    0x000111EB,
    0x00011999,
    0x000123D7,
    0x000130A3,
    0x00013AE1,
    0x000147AE,
    0x0001547A,
    0x000163D7,
    0x00017333,
    0x0001851E,
    0x00019999,
    0x0001AE14,
    0x0001C7AE,
    0x0001E147
};

#define MAX_SENSOR_GAIN 16
#define ISP_DGAIN_BASE 0x200
//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_DoAEOperation_ST
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_DoAEOperation_ST_AR0330(void)
{
#if 1
if(!gsEnableTestPattern)
{
    ISP_UINT32 again;//, dgain;

    if(ISP_IF_3A_GetSwitch(ISP_3A_ALGO_AE) != 1) return MMP_ERR_NONE;

    if (ISP_IF_AE_GetLightCond() <= 48)
        frame_div = 5;
    else 
        frame_div = 5; 
    switch (gISPFrameCnt % (frame_div-1)) {
    case 1:
        ISP_IF_AE_Execute();

        again = ISP_IF_AE_GetGain();
        //dgain = ISP_IF_AE_GetDGain();

        s_gain = again;// * dgain / ISP_IF_AE_GetDGainBase();

        gsSensorFunction->MMPF_Sensor_SetSensorShutter(ISP_IF_AE_GetShutter(), ISP_IF_AE_GetVsync());
        gsSensorFunction->MMPF_Sensor_SetSensorGain(s_gain);
        break;
    }
}
#endif
    return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_DoAEOperation_END
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_DoAEOperation_END_AR0330(void)
{
#if 1
if(!gsEnableTestPattern)
{
    gISPFrameCnt++;
    if(ISP_IF_3A_GetSwitch(ISP_3A_ALGO_AE) != 1) return MMP_ERR_NONE;

    switch (gISPFrameCnt % 4) {
    case 1:
        break;
    case 0:
        ISP_IF_AE_GetHWAcc(1);
#if (MotionDetection == 1)
        COLOR_StoreAEAcc();
#endif
        break;
    }
}
#endif
    return  MMP_ERR_NONE;
}


//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_DoAFOperation
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_DoAFOperation_AR0330(void)
{
#if SUPPORT_AUTO_FOCUS
    if(gbAutoFocus == MMP_TRUE){
        //VR_AF_GetAcc();
        ISP_IF_AF_GetHWAcc(1);
        //ISP_IF_R_DoAF();
    }
#endif

    return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_DoAFOperation
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_DoAFOperation_FrameStart_AR0330(void)
{
#if SUPPORT_AUTO_FOCUS
    if(gbAutoFocus == MMP_TRUE){
        //VR_AF_GetAcc();
        //ISP_IF_R_GetAFAcc();
        //ISP_IF_R_DoAF();
        {
            static ISP_UINT32 frame_cnt = 0;

            switch (frame_cnt++ % 1) {
            case 0:
                ISP_IF_AF_Execute();
                MOTOR_AR0330_VCM_SetAFPosition_Customer(ISP_IF_AF_GetPos(0));
                break;
            }
        }
    }
#endif

    return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_DoIQOperation_AR0330
//  Description :
//------------------------------------------------------------------------------
//extern MMP_UBYTE gbSkypeMode;

static MMP_ERR  MMPF_Sensor_DoIQOperation_AR0330(void)
{
    // switch IQ table if video format is H264
    //PCAM_USB_VIDEO_FORMAT vidFmt = pcam_get_info()->pCamVideoFormat;

    //if (vidFmt == PCAM_USB_VIDEO_FORMAT_H264)	ISP_IF_F_SetVideoMode(1);
    //else										ISP_IF_F_SetVideoMode(0);

    // set IQ at frame end to ensure frame sync	
    ISP_IF_IQ_SetAll();
#if SUPPORT_ISP_ENGINEERING_MODE_FUNCTION
    {
    extern MMP_USHORT PCAM_UpdateGAMMAtoRAM(void);
    PCAM_UpdateGAMMAtoRAM();
    }
#endif
    ISP_IF_IQ_CheckBypass();

    //RTNA_DBG_Str(0, "DoIQOperation_AR0330()\r\n");
	
    return  MMP_ERR_NONE;
}

// Steven ADD
//------------------------------------------------------------------------------
//  Function    : MMPF_SetLightFreq
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_SetLightFreq_AR0330(MMP_USHORT usMode)
{
#if 0

    RTNA_DBG_Str(0, "MMPF_SetLightFreq_AR0330 : ");
    RTNA_DBG_Short(0, usMode);
    RTNA_DBG_Str(0, "\r\n");

    /*
    typedef enum {
        VENUS_FLICKER_MODE_OFF              = 0,
        VENUS_FLICKER_MODE_AUTO             = 1,
        VENUS_FLICKER_MODE_60HZ             = 2,
        VENUS_FLICKER_MODE_50HZ             = 3,
        VENUS_FLICKER_MODE_CAL_BASESHUTTER  = 4
    } VENUS_FLICKER_MODE;
    */

    switch(usMode) {
    case 0:
    case 2:
        //gISPConfig.FlickerMode = VENUS_FLICKER_MODE_60HZ;
        ISP_IF_AE_SetFlicker(ISP_AE_FLICKER_60HZ);
        break;
    case 1:
    case 3:
        //gISPConfig.FlickerMode = VENUS_FLICKER_MODE_50HZ;
        ISP_IF_AE_SetFlicker(ISP_AE_FLICKER_50HZ);
        break;
    default:
        //gISPConfig.FlickerMode = VENUS_FLICKER_MODE_AUTO;
        ISP_IF_AE_SetFlicker(ISP_AE_FLICKER_AUTO);
    }
#endif

    return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_SetStableState_AR0330(MMP_BOOL bStableState)
{
    return  MMP_ERR_NONE;
}

MMP_ERR MMPF_SetHistEQState_AR0330(MMP_BOOL bHistEQState)
{

    return  MMP_ERR_NONE;
}

extern volatile MMP_UBYTE gbDramID;
static MMP_ERR  MMPF_Sensor_SetReg_AR0330(MMP_USHORT usAddr, MMP_USHORT usData)
{
    if((gbDramID == MMPF_DRAMID_WINBOND_SDR16) || (gbDramID == MMPF_DRAMID_WINBOND_SDR16_1_8V)){
        m_snr_I2cmAttribute.uI2cmID = MMPF_I2CM_ID_0;  // for AIT8433 70 pin package
    }
    else{
        m_snr_I2cmAttribute.uI2cmID = MMPF_I2CM_ID_1;  // for AIT8451 105 pin package
    }
    MMPF_I2cm_WriteReg(&m_snr_I2cmAttribute, usAddr, usData);
    return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_GetReg_AR0330(MMP_USHORT usAddr, MMP_USHORT *usData)
{
    *usData = 0xFF;
    if((gbDramID == MMPF_DRAMID_WINBOND_SDR16) || (gbDramID == MMPF_DRAMID_WINBOND_SDR16_1_8V)){
        m_snr_I2cmAttribute.uI2cmID = MMPF_I2CM_ID_0;  // for AIT8433 70 pin package
    }
    else{
        m_snr_I2cmAttribute.uI2cmID = MMPF_I2CM_ID_1;  // for AIT8451 105 pin package
    }
    MMPF_I2cm_ReadReg(&m_snr_I2cmAttribute, usAddr, usData);

    return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetImageScene_AR0330(MMP_USHORT imgSceneID)
{
#if 0
/*
typedef enum {
    ISP_SCENE_AUTO					= 0,	// scene mode
    ISP_SCENE_PORTRAIT				= 1,	// scene mode
    ISP_SCENE_LANDSCAPE				= 2,	// scene mode
    ISP_SCENE_SPORTS				= 3,	// scene mode
    ISP_SCENE_SUNSET				= 4,	// scene mode
    ISP_SCENE_DUSK					= 5,	// scene mode
    ISP_SCENE_DAWN					= 6,	// scene mode
    ISP_SCENE_NIGHT_SHOT			= 7,	// scene mode
    ISP_SCENE_AGAINST_LIGHT			= 8,	// scene mode
    ISP_SCENE_TEXT					= 9,	// scene mode
    ISP_SCENE_MANUAL				= 10,	// scene mode
    ISP_SCENE_INDOOR				= 11,	// scene mode
    ISP_SCENE_SNOW					= 12,	// scene mode
    ISP_SCENE_FALL					= 13,	// scene mode
    ISP_SCENE_WAVE					= 14,	// scene mode
    ISP_SCENE_FIREWORKS				= 15,	// scene mode
    ISP_SCENE_SHOW_WIN				= 16,	// scene mode
    ISP_SCENE_CANDLE				= 17,	// scene mode
    ISP_SCENE_NONE					= 18	// camera mode
} ISP_SCENE;
*/
    imgSceneID = (imgSceneID % (ISP_SCENE_NONE+1));

    RTNA_DBG_Str(3, "MMPF_SetImageScene_AR0330 : ");
    RTNA_DBG_Byte(3, imgSceneID);
    RTNA_DBG_Str(3, "\r\n");

    //if (g3AConfig.Control3A == ISP_3A_ENABLE)
        MMPF_Sensor_CheckFrameEnd(1);
    ISP_IF_F_SetScene(imgSceneID);
#endif

    return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetAEMode_AR0330(MMP_UBYTE ubAEMode, MMP_UBYTE ubISOMode)
{
#if 0
/*
typedef enum {
    AE_MODE_AUTO						= 0,
    AE_MODE_MANUAL						= 1,
    AE_MODE_ISO							= 2,
    AE_MODE_SHUTTER						= 3
} VENUS_AE_MODE;
*/
/*
typedef enum {
    AE_ISO_AUTO					= 0,
    AE_ISO_50					= 1,
    AE_ISO_100					= 2,
    AE_ISO_200					= 3,
    AE_ISO_400					= 4,
    AE_ISO_800					= 5,
    AE_ISO_1600					= 6,
    AE_ISO_3200					= 7,
    ISP_AE_ISO_NUM
} VENUS_AE_ISO;
*/
    #if 0 //FIXME, VSN_V2
    if (ubAEMode == 3)
        ISP_IF_AE_SetISO(ISP_AE_MODE_AUTO);
    else
    #endif
        ISP_IF_AE_SetISO(ubISOMode);
#endif
	
    return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetAFMode_AR0330(MMP_UBYTE ubAFMode)
{
#if 0
/*
typedef enum {
    VENUS_AF_MODE_AUTO					= 0,
    VENUS_AF_MODE_MANUAL				= 1,
    VENUS_AF_MODE_MACRO					= 2,
    VENUS_AF_MODE_FULL					= 3,
    VENUS_AF_MODE_MOTOR_TEST            = 4,
    VENUS_AF_MODE_NULL					= 5
} VENUS_AF_MODE;
*/
    RTNA_DBG_Str(3, "MMPF_Sensor_SetAFMode_AR0330 : ");
    RTNA_DBG_Byte(3, ubAFMode);
    RTNA_DBG_Str(3, "\r\n");

    //gISPConfig.AutoFocusMode = (MMP_UBYTE)ubAFMode;
    //if (g3AConfig.Control3A == ISP_3A_ENABLE)
    //	MMPF_Sensor_CheckFrameEnd(1);
    ISP_IF_AF_SetMode(ubAFMode);
#endif

    return  MMP_ERR_NONE;
}

//======================================================================//
// function : MMPF_Sensor_SetImageEffect                                //
// parameters:                                                          //
// return :                                                             //
// description :                                                        //
//======================================================================//
static MMP_ERR  MMPF_Sensor_SetImageEffect_AR0330(MMP_USHORT imgEffectID)
{
#if 0
/*
typedef enum {
    ISP_IMAGE_EFFECT_NORMAL			= 0,
    ISP_IMAGE_EFFECT_GREY			= 1,
    ISP_IMAGE_EFFECT_SEPIA			= 2,
    ISP_IMAGE_EFFECT_NEGATIVE		= 3,
    ISP_IMAGE_EFFECT_ANTIQUE		= 4,
    ISP_IMAGE_EFFECT_WATERCOLOR		= 5,
    ISP_IMAGE_EFFECT_PORTRAIT		= 6,
    ISP_IMAGE_EFFECT_LANDSCAPE		= 7,
    ISP_IMAGE_EFFECT_SUNSET			= 8,
    ISP_IMAGE_EFFECT_DUSK			= 9,
    ISP_IMAGE_EFFECT_DAWN			= 10,
    ISP_IMAGE_EFFECT_RED			= 11,
    ISP_IMAGE_EFFECT_GREEN			= 12,
    ISP_IMAGE_EFFECT_BLUE			= 13,
    ISP_IMAGE_EFFECT_YELLOW			= 15,
    ISP_IMAGE_EFFECT_EMBOSS			= 17,
    ISP_IMAGE_EFFECT_OIL			= 18,
    ISP_IMAGE_EFFECT_BW				= 19,
    ISP_IMAGE_EFFECT_SKETCH			= 20,
    ISP_IMAGE_EFFECT_CRAYONE		= 21,
    ISP_IMAGE_EFFECT_WHITEBOARD		= 22,
    ISP_IMAGE_EFFECT_BLACKBOARD		= 23,
    ISP_IMAGE_EFFECT_VIVID			= 24,
    ISP_IMAGE_EFFECT_NUM
} ISP_IMAGE_EFFECT;
*/

    imgEffectID = (imgEffectID % (ISP_IMAGE_EFFECT_NUM+1));

    RTNA_DBG_Str(3, "MMPF_Sensor_SetImageEffect_AR0330 : ");
    RTNA_DBG_Byte(3, imgEffectID);
    RTNA_DBG_Str(3, "\r\n");

    //gISPConfig.ImageEffect = (MMP_USHORT)imgEffectID;
    //if (g3AConfig.Control3A == ISP_3A_ENABLE)
    //	MMPF_Sensor_CheckFrameEnd(1);
    ISP_IF_F_SetImageEffect(imgEffectID);
#endif

    return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetAWBType_AR0330(MMP_UBYTE ubType)
{
#if 0
    RTNA_DBG_Str(3, "MMPF_Sensor_SetAWBType_AR0330 : ");
    RTNA_DBG_Byte(3, ubType);
    RTNA_DBG_Str(3, "\r\n");

    cAWBtype = ubType;
#endif
    return  MMP_ERR_NONE;
}
static MMP_ERR  MMPF_Sensor_SetContrast_AR0330(MMP_SHORT ubLevel)
{
#if 0
    RTNA_DBG_Str(3, "MMPF_Sensor_Contrast_AR0330 : ");
    RTNA_DBG_Byte(3, ubLevel);
    RTNA_DBG_Str(3, "\r\n");

    //gISPConfig.ContrastLevel = ubLevel;
    ISP_IF_F_SetContrast(ubLevel);
#endif

    return  MMP_ERR_NONE;
}
static MMP_ERR  MMPF_Sensor_SetSaturation_AR0330(MMP_SHORT ubLevel)
{
#if 0
    RTNA_DBG_Str(3, "MMPF_Sensor_SetSaturation_AR0330 : ");
    RTNA_DBG_Byte(3, ubLevel);
    RTNA_DBG_Str(3, "\r\n");

    //gISPConfig.SaturationLevel = ubLevel;
    ISP_IF_F_SetSaturation(ubLevel);
#endif

    return  MMP_ERR_NONE;
}
static MMP_ERR  MMPF_Sensor_SetSharpness_AR0330(MMP_SHORT ubLevel)
{
#if 0
    RTNA_DBG_Str(3, "MMPF_Sensor_SetSharpness_AR0330 : ");
    RTNA_DBG_Byte(3, ubLevel);
    RTNA_DBG_Str(3, "\r\n");

    //gISPConfig.SharpnessLevel = ubLevel;
    ISP_IF_F_SetSharpness(ubLevel);
#endif

    return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetHue_AR0330(MMP_SHORT ubLevel)
{
#if 0
    RTNA_DBG_Str(3, "MMPF_Sensor_SetHue_AR0330 : ");
    RTNA_DBG_Byte(3, ubLevel);
    RTNA_DBG_Str(3, "\r\n");

    ISP_IF_F_SetHue(ubLevel);
#endif

    return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetGamma_AR0330(MMP_SHORT ubLevel)
{
#if 0
    RTNA_DBG_Str(3, "MMPF_Sensor_SetGamma_AR0330 : ");
    RTNA_DBG_Byte(3, ubLevel);
    RTNA_DBG_Str(3, "\r\n");

    ISP_IF_F_SetGamma(ubLevel);
#endif

    return  MMP_ERR_NONE;
}

/*static MMP_ERR  MMPF_Sensor_SetBacklight_AR0330(MMP_UBYTE ubLevel)
{
#if 0
    RTNA_DBG_Str(3, "MMPF_Sensor_SetBacklight_AR0330 : ");
    RTNA_DBG_Byte(3, ubLevel);
    RTNA_DBG_Str(3, "\r\n");

    //	ISP_IF_F_SetBacklight(ubLevel);
    if(ubLevel > 1){
        ISP_IF_F_SetWDR(ISP_WDR_DISABLE);
    }
    else{
        ISP_IF_F_SetWDR(ISP_WDR_ENABLE);
    }
#endif

    return  MMP_ERR_NONE;
}
*/

static void  MMPF_Sensor_SetCaptureISPSetting_AR0330(MMP_UBYTE usCaptureBegin)
{
#if 0
    AITPS_VIF   pVIF = AITC_BASE_VIF;
    MMP_ULONG   ulVIF_Width, ulVIF_Height;

    /* ToDo: setting IOS and ISP windows*/
    if(MMP_TRUE == usCaptureBegin){
        ulVIF_Width = (pVIF->VIF_GRAB[vif_id].PIXL_ED - pVIF->VIF_GRAB[vif_id].PIXL_ST + 1);
        ulVIF_Height = (pVIF->VIF_GRAB[vif_id].LINE_ED - pVIF->VIF_GRAB[vif_id].LINE_ST + 1);
    }
#endif
	
    return;
}

/*Prepare for raw preview zoom*/
static void  MMPF_Sensor_SetISPWindow_AR0330(MMP_ULONG ulWidth, MMP_ULONG ulHeight)
{
    //gSensorFunc.SetISPWindows(ulWidth,ulHeight);
    return;
}

/*Check AIT can preview in this resolution*/
static MMP_UBYTE  MMPF_Sensor_CheckPreviewAbility_AR0330(MMP_USHORT usPreviewmode)
{
#if 0
    switch(usPreviewmode){
        case 0:                 //2M can't preview
            return MMP_TRUE;
            break;
        case 1:                 //1.3M can preview
            return MMP_TRUE;
            break;
    }
#endif
	
    return MMP_TRUE;            //5M and 1.3M always can preview
}

static void SetAFWin_AR0330(MMP_USHORT usIndex, MMP_USHORT usPreviewWidth, MMP_USHORT usPreviewHeight,
					MMP_USHORT  usStartX, MMP_USHORT  usStartY, MMP_USHORT  usWidth, MMP_USHORT  usHeight)
{

}

static void SetAFEnable_AR0330(MMP_UBYTE enable)
{
		ISP_IF_AF_Control(ISP_AF_START);
}

static MMP_ERR MMPF_Sensor_SetAEEnable_AR0330(MMP_UBYTE bEnable)
{
    ISP_IF_3A_SetSwitch(ISP_3A_ALGO_AE, bEnable);

    return MMP_ERR_NONE;
}

static MMP_ERR MMPF_Sensor_SetAWBEnable_AR0330(MMP_UBYTE bEnable)
{
#if 0
    if (bEnable) {
        g3AConfig.AWB_Enabled    = ON;
        g3AConfig.AWBRGB_Enabled = ON;
    }
    else {
        g3AConfig.AWB_Enabled    = OFF;
        g3AConfig.AWBRGB_Enabled = OFF;
    }
#endif

    if(bEnable)
        ISP_IF_AWB_SetMode(ISP_AWB_MODE_AUTO);
    else
        ISP_IF_AWB_SetMode(ISP_AWB_MODE_MANUAL);

    return MMP_ERR_NONE;
}
static void SetAEsmooth_AR0330(MMP_UBYTE smooth)  {return;}
static MMP_ERR MMPF_Sensor_SetExposureValue_AR0330(MMP_UBYTE ev)
{
#if 0
    RTNA_DBG_Str(3, "MMPF_Sensor_SetExposureValue_AR0330 : ");
    //RTNA_DBG_Byte(3, gISPConfig.EV);
    //RTNA_DBG_Str(3, " : ");
    RTNA_DBG_Byte(3, ev);
    RTNA_DBG_Str(3, "\r\n");

    ISP_IF_AE_SetEV(ev);
#endif

    return MMP_ERR_NONE;
}

static MMP_UBYTE GetAFPosition_AR0330(void)
{
    return 0;/*volatile MMP_UBYTE *GPIO_BASE_B = (volatile MMP_UBYTE *)0x80009400;  return GPIO_BASE_B[0xB0];*/
}

static MMP_UBYTE GetAFEnable_AR0330(void)
{
    return ISP_IF_AF_GetResult();
}

static MMP_UBYTE GetExposureValue_AR0330  (void){return ISP_IF_AE_GetEV();}
static MMP_UBYTE GetAEsmooth_AR0330       (void){return 0;}
//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_Set3AStatus
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR	MMPF_Sensor_Set3AStatus_AR0330(MMP_BOOL bEnable)
{
    #if 1
    MMPF_Sensor_3A_SetInterrupt(bEnable);

    if (bEnable)
        ISP_IF_3A_Control(ISP_3A_ENABLE);
    else
        ISP_IF_3A_Control(ISP_3A_DISABLE);
    #endif
    return	MMP_ERR_NONE;
}

static void  MMPF_Sensor_SetColorID_AR0330(MMPF_SENSOR_ROTATE_TYPE RotateType)
{
    switch(RotateType) {
    case MMPF_SENSOR_ROTATE_NO_ROTATE:
        gsSensorFunction->MMPF_Sensor_SetReg(0x3040, 0x0000);
        ISP_IF_IQ_SetColorID(0);
        break;
    case MMPF_SENSOR_ROTATE_RIGHT_90:
        break;
    case MMPF_SENSOR_ROTATE_RIGHT_180:
        gsSensorFunction->MMPF_Sensor_SetReg(0x3040, 0xC000);
        ISP_IF_IQ_SetColorID(0);//3
        break;
    case MMPF_SENSOR_ROTATE_RIGHT_270:
        break;
    case MMPF_SENSOR_ROTATE_H_MIRROR:
        gsSensorFunction->MMPF_Sensor_SetReg(0x3040, 0x4000);
        ISP_IF_IQ_SetColorID(0);//1
        break;
    case MMPF_SENSOR_ROTATE_V_FLIP:
        gsSensorFunction->MMPF_Sensor_SetReg(0x3040, 0x8000);
        ISP_IF_IQ_SetColorID(0);//2
        break;
    }

    ISP_IF_IQ_SetDirection((ISP_UINT8)RotateType);
    return;
}

const ISP_UINT8 get_AR0330_gain_Customer[128] = 
{
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,

    0x00, //0x10
    0x01,
    0x02,
    0x03,
    0x04,
    0x05,
    0x06,
    0x07,
    0x08,
    0x09,
    0x0a,
    0x0b,
    0x0c,
    0x0d,
    0x0e,
    0x0f,


    0x11,//0x20
    0x11,
    0x12,
    0x12,
    0x13,
    0x13,
    0x14,
    0x14,
    0x15,
    0x15,
    0x16,
    0x16,
    0x17,
    0x17,
    0x18,
    0x18,


    0x19,//0x30
    0x19,
    0x1a,
    0x1a,
    0x1b,
    0x1b,
    0x1c,
    0x1c,
    0x1d,
    0x1d,
    0x1e,
    0x1e,
    0x1f,
    0x1f,
    0x31,
    0x31,

    0x31,//0x40
    0x31,
    0x31,
    0x31,
    0x32,
    0x32,
    0x32,
    0x32,
    0x33,
    0x33,
    0x33,
    0x33,
    0x34,
    0x34,
    0x34,
    0x34,

    0x35,//0x50
    0x35,
    0x35,
    0x35,
    0x36,
    0x36,
    0x36,
    0x36,
    0x37,
    0x37,
    0x37,
    0x37,
    0x38,
    0x38,
    0x38,
    0x38,

    0x39,//0x60
    0x39,
    0x39,
    0x39,
    0x3a,
    0x3a,
    0x3a,
    0x3a,
    0x3b,
    0x3b,
    0x3b,
    0x3b,
    0x3c,
    0x3c,
    0x3c,
    0x3c,

    0x3d,//0x70
    0x3d,
    0x3d,
    0x3d,
    0x3e,
    0x3e,
    0x3e,
    0x3e,
    0x3f,
    0x3f,
    0x3f,
    0x3f,
    0x71,
    0x71,
    0x71,
    0x71,
};

static void MMPF_Sensor_SetSensorGain_AR0330(MMP_ULONG gain)
{
#if 1
    ISP_UINT16 sensor_again;
    ISP_UINT16 sensor_dgain;

    gain = gain * 64 / 0x100;  //0x40 = 1x , for sensor min_gain limit 1.23x 79/64 = 1.235

    // sean@2011_03_25, if set gain = cur gain, just return
    //dbg_printf(0,"#>Set.Sensor.Gain:%x\r\n",gain);
    // Sensor Gain Mapping
    
    if(gain < 0x80){
        // <1X
        sensor_dgain = gain << 1;
        sensor_again = 0x00;
    }
    else if(gain < 0x100){
        // <2X
        sensor_dgain = gain;
        sensor_again = 0x10;
    }
    else if(gain < 0x200){
        // 4X ~ 8X (AG=4x)
        sensor_dgain = gain >> 1;
        sensor_again = 0x20;
    }
    else{
        // 8X ~16X (AG=8x)
        sensor_dgain = gain >> 2;
        sensor_again = 0x30;
    }

    MMPF_Sensor_SetSensorReg(0x305E, sensor_dgain);
    MMPF_Sensor_SetSensorReg(0x3060, sensor_again);
#endif
}

static void MMPF_Sensor_SetSensorShutter_AR0330(MMP_ULONG shutter, MMP_ULONG vsync)
{
#if 1
    MMP_ULONG new_vsync;
    MMP_ULONG new_shutter;
    vsync = g_SNR_LineCntPerSec * ISP_IF_AE_GetVsync() / ISP_IF_AE_GetVsyncBase();
    shutter = g_SNR_LineCntPerSec * ISP_IF_AE_GetShutter() / ISP_IF_AE_GetShutterBase();
    new_vsync =  VR_MAX(vsync, shutter + 5);  //+8
    new_shutter = VR_MIN(VR_MAX(shutter, 1), new_vsync - 5);
    //	MMP_ULONG ExtraVsyncWidth;

    gsSensorFunction->MMPF_Sensor_SetReg(0x300A, new_vsync);
    gsSensorFunction->MMPF_Sensor_SetReg(0x3012, new_shutter);
#endif
}

MMPF_SENSOR_FUNCTION  SensorFunction_AR0330 =
{
    MMPF_Sensor_Initialize_AR0330,
    MMPF_Sensor_InitializeVIF_AR0330,
    MMPF_Sensor_InitializeISP_AR0330,
    MMPF_Sensor_PowerDown_AR0330,
    MMPF_Sensor_SetFrameRate_AR0330,
    MMPF_Sensor_ChangeMode_AR0330,
    MMPF_Sensor_ChangePreviewMode_AR0330,
    MMPF_Sensor_SetPreviewMode_AR0330,
    MMPF_Sensor_SetReg_AR0330,
    MMPF_Sensor_GetReg_AR0330,
    MMPF_Sensor_DoAWBOperation_AR0330,
    MMPF_Sensor_DoAEOperation_ST_AR0330,
    MMPF_Sensor_DoAEOperation_END_AR0330,
    MMPF_Sensor_DoAFOperation_AR0330,
    MMPF_Sensor_DoAFOperation_FrameStart_AR0330,
    MMPF_Sensor_DoIQOperation_AR0330,
    MMPF_Sensor_SetImageEffect_AR0330,
    MMPF_SetLightFreq_AR0330,
    MMPF_SetStableState_AR0330,
    MMPF_SetHistEQState_AR0330,
    MMPF_Sensor_SetAFPosition_AR0330,
    SetAFWin_AR0330,
    SetAFEnable_AR0330,
    MMPF_Sensor_SetAEEnable_AR0330,
    MMPF_Sensor_SetAWBEnable_AR0330,
    MMPF_Sensor_SetExposureValue_AR0330,
    SetAEsmooth_AR0330,
    MMPF_Sensor_SetImageScene_AR0330,
    GetAFPosition_AR0330,
    GetAFEnable_AR0330,
    GetExposureValue_AR0330,
    GetAEsmooth_AR0330,
    MMPF_Sensor_SetAWBType_AR0330,
    MMPF_Sensor_SetContrast_AR0330,
    MMPF_Sensor_SetSaturation_AR0330,
    MMPF_Sensor_SetSharpness_AR0330,
    MMPF_Sensor_SetHue_AR0330,
    MMPF_Sensor_SetGamma_AR0330,
    //   MMPF_Sensor_SetBacklight_AR0330,
    MMPF_Sensor_SetAEMode_AR0330,
    MMPF_Sensor_SetAFMode_AR0330,
    MMPF_Sensor_SetCaptureISPSetting_AR0330,
    MMPF_Sensor_SetISPWindow_AR0330,
    MMPF_Sensor_CheckPreviewAbility_AR0330,
    MMPF_Sensor_Set3AStatus_AR0330,
    MMPF_Sensor_SetColorID_AR0330,
    MMPF_Sensor_SetSensorGain_AR0330,
    MMPF_Sensor_SetSensorShutter_AR0330
};

MMP_USHORT SNR_AR0330_Reg_Init_Customer[] = {
    0x301A, 0x0059, //RESET_REGISTER = 89
    0x31AE, 0x0202, //2lane MIPI
    0x301A, 0x0058, //DISABLE BIT[0]

    0x3ED2, 0x0146,
    0x3ED6, 0x66CC,
    0x3ED8, 0x8C42,

    0x3064, 0x1802,
    0x3078, 0x0001,
    0x31E0, 0x0003,
    0x3046, 0x4038, //FOR DEBUG
    0x3048, 0x8480, //FOR DEBUG

    //[PLL_settings]
    0x302A, 0x0005, //VT_PIX_CLK_DIV = 5
    0x302C, 0x0002, //VT_SYS_CLK_DIV = 2
    0x302E, 0x0004, //PRE_PLL_CLK_DIV = 4
    0x3030, 0x0052 + 0x03, //PLL_MULTIPLIER = 82
    0x3036, 0x000A, //OP_PIX_CLK_DIV = 10
    0x3038, 0x0001, //OP_SYS_CLK_DIV = 1
    0x31AC, 0x0A0A, //DATA_FORMAT_BITS = 2570
    0x31B0, 0x0028,
    0x31B2, 0x000E,
    0x31B4, 0x2743,
    0x31B6, 0x114E,
    0x31B8, 0x2049,
    0x31BA, 0x0186,
    0x31BC, 0x8005,
    0x31BE, 0x2003,

    //[Timing_settings]
    //Context A
    0x3002, 0x0058, //Y_ADDR_START = 120
    0x3004, 0x0006 - 0x04, //X_ADDR_START = 6
    0x3006, 0x0587 + 0x0C, //Y_ADDR_END = 1415
    0x3008, 0x0905 + 0x04, //X_ADDR_END = 2309
    0x300A, 0x051C, //FRAME_LENGTH_LINES = 1308
    0x300C, 0x04E0 + 0x04, //LINE_LENGTH_PCK = 1248
    0x3012, 0x051B, //COARSE_INTEGRATION_TIME = 1307
    0x3014, 0x0000, //FINE_INTEGRATION_TIME = 0
    0x30A2, 0x0001, //X_ODD_INC = 1
    0x30A6, 0x0001, //Y_ODD_INC = 1

    0x3040, 0x0000, //READ_MODE = 0
    0x3042, 0x0209, //EXTRA_DELAY = 521
    0x30BA, 0x002C, //DIGITAL_CTRL = 44

    0x3088, 0x80BA, //SEQ_CTRL_PORT = 32954
    0x3086, 0x0253, //SEQ_DATA_PORT = 595
    0x301A, 0x005C, //RESET_REGISTER = 92  ENABLE BIT[2]
};

void SNR_AR0330_InitSensor_Customer(void) {
    // implement your initialize sensor routine here ==============================================
    ISP_UINT32 i;
    // set register...........
    RTNA_DBG_Str(0, "set sensor reg\r\n");
    for (i = 0; i < sizeof(SNR_AR0330_Reg_Init_Customer)/4; i++) {
        gsSensorFunction->MMPF_Sensor_SetReg(SNR_AR0330_Reg_Init_Customer[i*2], SNR_AR0330_Reg_Init_Customer[i*2+1]);
        MMPF_OS_Sleep_MS(1);
    }

    if (gsEnableTestPattern) {  //set H.264 test pattern
        gsSensorFunction->MMPF_Sensor_SetReg(0x3070,0x02);  //0:No pattern 1:Solid color 2:100% Vertical 3:Fade-to-Gray Vertical Color Bars
        gsEnableTestPattern = 0;
    }

    //MMPF_OS_Sleep_MS(20);
    //ISP_IF_AE_SetBaseShutter( BASE_SHUTTER_50HZ, BASE_SHUTTER_60HZ);
    //ISP_IF_AE_SetMinFPSx10(75);

    // Set preview resolution as default
    //SNR_AR0330_SetSensorResolution_Customer(ISP_SENSOR_RESOL_2304x1296);//Bug fix, must call ISP_IF_IQ_SetSysMode first
}

void SNR_AR0330_SetSensorAddMode_Customer(ISP_UINT8 enable)
{

}

void SNR_AR0330_SetSensorResolution_Customer(ISP_SENSOR_RESOL res)
{
    // implement your change sensor resolution routine here =======================================

    MMP_ULONG VIFGrab_H_Start, VIFGrab_H_Length, VIFGrab_V_Start, VIFGrab_V_Length;

    ISP_IF_AE_SetMaxSensorFPSx10(300);
#if (CUSTOMER == QDR)
    ISP_IF_AE_SetMinFPSx10(100);
#endif
    switch (res) {
        case ISP_SENSOR_RESOL_2304x1296:
        // set register...........
        //for (i = 0; i < VR_ARRSIZE(SNR_AR0330_Reg_2304x1296_Customer)/2; i++) {
        //    gsSensorFunction->MMPF_Sensor_SetReg(SNR_AR0330_Reg_2304x1296_Customer[i*2], SNR_AR0330_Reg_2304x1296_Customer[i*2+1]);
        //}

        // set target fps and corresponding sensor vsync
        //ISP_IF_AE_SetSensorVsync(0x0550, 30*10);//bossino fix m2ts AV sync @0928 ISP_IF_SNR_SetFPS(0x0348, 30);

        // set vif grab range which is fetched to ISP (for lens shading and 3A window calculation)
        VIFGrab_H_Start     = 1;
        VIFGrab_H_Length    = gsSensorPreviewWidth[0] + 8;
        VIFGrab_V_Start     = 1;
        VIFGrab_V_Length    = gsSensorPreviewHeight[0] + 12;

        // calcuate shading ratio
        {
            ISP_UINT32 base_x, base_y;
            ISP_UINT32 x_scale_n = 0x200;
            ISP_UINT32 y_scale_n = 0x200;
            ISP_IF_IQ_GetCaliBase(&base_x, &base_y);

            x_scale_n = VIFGrab_H_Length * 0x200 / base_x;
            y_scale_n = VIFGrab_V_Length * 0x200 / base_y;

            ISP_IF_IQ_SetCaliRatio(	x_scale_n,	//x_scale_n, 
                                    0x200,		//x_scale_m, 
                                    0,			//x_offset, 
                                    y_scale_n,	//y_scale_n, 
                                    0x200,		//y_scale_m, 
                                    0);			//y_offset
        }

        g_SNR_LineCntPerSec = BASE_SHUTTER_60HZ * 120; 
        ISP_IF_AE_SetMaxSensorFPSx10(30 * 10);
				
        ISP_IF_IQ_SetISPInputLength(VIFGrab_H_Length, VIFGrab_V_Length);

        // set color id
        #if SENSOR_ROTATE_180
        ISP_IF_IQ_SetColorID(3);
        #else
        ISP_IF_IQ_SetColorID(0);// mirror is 3
        #endif		
        break;
        case ISP_SENSOR_RESOL_1280x720:
        // set register...........
        //for (i = 0; i < VR_ARRSIZE(SNR_AR0330_Reg_1280x720_Customer)/2; i++) {
        //    gsSensorFunction->MMPF_Sensor_SetReg(SNR_AR0330_Reg_1280x720_Customer[i*2], SNR_AR0330_Reg_1280x720_Customer[i*2+1]);
        //}

        // set target fps and corresponding sensor vsync
        //ISP_IF_AE_SetSensorVsync(0x0348, 30*10);//bossino fix m2ts AV sync @0928 ISP_IF_SNR_SetFPS(0x0348, 30);

        // set vif grab range which is fetched to ISP (for lens shading and 3A window calculation)
        VIFGrab_H_Start     = 1;
        VIFGrab_H_Length    = 1280 + 8;
        VIFGrab_V_Start     = 1;
        VIFGrab_V_Length    = 720 + 12;

        ISP_IF_IQ_SetISPInputLength(VIFGrab_H_Length, VIFGrab_V_Length);

        // set scaler downsample rate (for scaler calculation)
        //ISP_IF_SNR_SetDownSample(1, 1);

        // set color id
        #if SENSOR_ROTATE_180
        ISP_IF_IQ_SetColorID(3);
        #else
        ISP_IF_IQ_SetColorID(0);// mirror is 3
        #endif		

        // calcuate shading ratio
        {
            ISP_UINT32 base_x, base_y;
            ISP_UINT32 x_scale_n = 0x200;
            ISP_UINT32 y_scale_n = 0x200;
            ISP_IF_IQ_GetCaliBase(&base_x, &base_y);

            x_scale_n = VIFGrab_H_Length * 0x200 / base_x;
            y_scale_n = VIFGrab_V_Length * 0x200 / base_y;

            ISP_IF_IQ_SetCaliRatio(	x_scale_n,	//x_scale_n, 
                                    0x200,		//x_scale_m, 
                                    0,			//x_offset, 
                                    y_scale_n,	//y_scale_n, 
                                    0x200,		//y_scale_m, 
                                    0);			//y_offset
        }
        break;
    }
	
    // end of your implementation =================================================================

    // set VIF OPR (Actual sensor output size)
    {
        AITPS_VIF  pVIF = AITC_BASE_VIF;
        volatile MMP_BYTE* pISP = (volatile MMP_BYTE*)AITC_BASE_ISP;

        pVIF->VIF_GRAB[vif_id].PIXL_ST = VIFGrab_H_Start;
        pVIF->VIF_GRAB[vif_id].PIXL_ED = VIFGrab_H_Start + VIFGrab_H_Length -1;
        pVIF->VIF_GRAB[vif_id].LINE_ST = VIFGrab_V_Start ;
        pVIF->VIF_GRAB[vif_id].LINE_ED = VIFGrab_V_Start + VIFGrab_V_Length -1;
        pVIF->VIF_INT_LINE_NUM_0[vif_id] = VIFGrab_V_Length - 121;//61;

#if 1	
        dbg_printf(3,"ViF(xs,xe,ys,ye)=(%d,%d,%d,%d)\r\n",pVIF->VIF_GRAB[vif_id].PIXL_ST,pVIF->VIF_GRAB[vif_id].PIXL_ED,pVIF->VIF_GRAB[vif_id].LINE_ST,pVIF->VIF_GRAB[vif_id].LINE_ED);
        dbg_printf(3, "[0] VIFGrab_H_Length = %d, VIFGrab_V_Length = %d\r\n", VIFGrab_H_Length, VIFGrab_V_Length); 
#endif

        if (m_gsISPCoreID == 868) {
            // ISP pipeline selection
            //APICAL_XBYTE[APICAL_CTL_REG1] &= ~(0x80); // clear auto size
            pISP[0x0B] = 0x30;
            pISP[0x09] = 0x0C;

            // IP ColorID setting
            //pISP[0x09] &= ~(0xF0);
            //pISP[0x09] |= (ISP_IF_SNR_GetColorID() == 0 ? 3 : (ISP_IF_SNR_GetColorID() == 1 ? 2 : (ISP_IF_SNR_GetColorID() == 2 ? 1: 0))) * (0x50);
        }
    }
    //================
    // set iq (NR, Edge, CCM, Gamma, etc.) and functions (saturation, contrast, sharpness, hue, etc.)
    ISP_IF_IQ_SetAll();

    // SetBeforePreview and SetBeforeCapture should be called after getting new configurations of the current resolution
    if (gSystemMode  == VENUS_SYSTEM_MODE_SNAPSHOT) {
        // update AE before capture
        ISP_IF_AE_UpdateBeforeCapture();

        // update AWB before capture
        ISP_IF_AWB_UpdateBeforeCapture();

        // special settings for capture could be set here =============================================
        {
        }
        // end of special settings ====================================================================
    } else if (gSystemMode == VENUS_SYSTEM_MODE_PREVIEW) {
        // update AE before preview
        ISP_IF_AE_UpdateBeforePreview();

        // update AWB before preview
        ISP_IF_AWB_UpdateBeforePreview();
    }

    // set direction (color ID, orientation, etc.)
    ISP_IF_IQ_SetDirection(ISP_IQ_DIRECTION_ORIGINAL);

    // set exposure parameters
    //ISP_IF_IQ_SetAEGain(ISP_IF_AE_GetDGain());
    //gsSensorFunction->MMPF_Sensor_SetSensorGain(ISP_IF_AE_GetAGain());
    //gsSensorFunction->MMPF_Sensor_SetSensorShutter(ISP_IF_AE_GetShutter(), ISP_IF_AE_GetVsync());

    ISP_IF_IQ_SetAWBGains(ISP_IF_AWB_GetGainR(), ISP_IF_AWB_GetGainG(), ISP_IF_AWB_GetGainB(), ISP_IF_AWB_GetGainBase());

    // update ISP window
    ISP_IF_IQ_UpdateInputSize();

    // check if modules are bypassed
    ISP_IF_IQ_CheckBypass();

    // force update iq to hardware
    ISP_IF_IQ_UpdateOprtoHW(ISP_IQ_SWITCH_ALL, 1);
}
#if (MotionDetection == 1)
static MMP_ULONG AEAcc_temp[9]={0xFFFF};
extern MMP_ULONG AEAcc_Buffer[9];
void COLOR_StoreAEAcc(void)
{
    MMP_SHORT i;
    for(i=0;i<9;i++)
    {
        AEAcc_temp[i] = AEAcc_Buffer[i];
    }
}

void COLOR_CopyAEAcc(MMP_ULONG* addr)
{
    struct _FRAME_H264_PH *header = (struct _FRAME_H264_PH *)addr;
    MMP_SHORT i;
    for(i=0;i<9;i++)
    {
    	header->dwAEAcc[i] = AEAcc_temp[i];
    }
    header->dwAELightCond = ISP_IF_AE_GetLightCond();
    header->dwAWB_GainRValue = ISP_IF_AWB_GetGainR();
    header->dwAWB_GainBValue  = ISP_IF_AWB_GetGainB();
}
#endif

#if SUPPORT_AUTO_FOCUS
void MOTOR_AR0330_VCM_InitMotor_Customer(void)
{
    //T.B.D
    dbg_printf(3, "###MOTOR_AR0330_VCM_InitMotor_Customer###\r\n");
}


void MOTOR_AR0330_VCM_EnterStandby_Customer(MMP_USHORT af_pos)
{
    //VR_Motor_SmoothMove(af_pos);
}

void MOTOR_AR0330_VCM_SetAFPosition_Customer(MMP_USHORT af_pos)
{
    //dbg_printf(3, "af_pos = %d\r\n", af_pos);
}

MMP_UBYTE MOTOR_AR0330_VCM_CheckAFreachPosition_Customer(MMP_USHORT af_pos)
{
    return 1;
}
#endif

#if (BIND_SENSOR_AR0330== 1)
MMPF_SENSOR_FUNCTION  *SensorFunction_Module0 = &SensorFunction_AR0330;
#endif

#if (BIND_SENSOR_AR0330== 2)
MMPF_SENSOR_FUNCTION  *SensorFunction_Module1 = &SensorFunction_AR0330;
#endif

#endif  //BIND_SENSOR_AR0330
#endif
